﻿using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Web;

//namespace VonPortal.Web.Html
//{
/// <summary>
/// 扩展Html功能，增加页面信息引入功能，支持引入js和css文件等
/// </summary>
public static class HtmlExtensions
{
    /// <summary>
    /// 引入命令
    /// </summary>
    /// <param name="section">引入段落标识，Header,footer</param>
    /// <param name="name">引入内容标志</param>
    /// <param name="template">要引入的内容</param>
    /// <example>
    /// @Html.Import(&quot;header&quot;, &quot;zTreeStyle_css&quot;, @&lt;link rel=&quot;stylesheet&quot; href=&quot;/content/zTreeStyle.css&quot; type=&quot;text / css&quot;&gt;)
    /// </example>
    public static HtmlString Import(this HtmlHelper htmlHelper, string section, string name, Func<object, HelperResult> template)
    {
        foreach (object key in htmlHelper.ViewContext.HttpContext.Items.Keys)
        {
            string[] keySection = key.ToString().Split(new char[] { '_' });
            if (keySection.Length == 3 && keySection[0] == "von" && keySection[2].Equals(name, StringComparison.OrdinalIgnoreCase))
                htmlHelper.ViewContext.HttpContext.Items.Remove(key);
        }
        htmlHelper.ViewContext.HttpContext.Items["von_" + section.ToLower() + "_IMPORT_" + name.ToLower()] = template;
        return MvcHtmlString.Empty;
    }
    /// <summary>
    /// 提取引入内容
    /// </summary>
    /// <param name="htmlHelper"></param>
    /// <param name="section">段落名称</param>
    /// <returns>要引入的html内容</returns>
    public static IHtmlString RenderImports(this HtmlHelper htmlHelper, string section)
    {
        string sectionKey = "von_" + section.ToLower() + "_IMPORT_";
        foreach (object key in htmlHelper.ViewContext.HttpContext.Items.Keys)
        {
            if (key.ToString().StartsWith(sectionKey))
            {
                var template = htmlHelper.ViewContext.HttpContext.Items[key] as Func<object, HelperResult>;
                if (template != null)
                {
                    htmlHelper.ViewContext.Writer.Write(template(null));
                }
            }
        }
        return MvcHtmlString.Empty;
    }
    /// <summary>
    /// span 组件内容
    /// </summary>
    /// <param name="helper"></param>
    /// <param name="id">标识码</param>
    /// <param name="text">内容</param>
    /// <param name="css">样式单名称即class名称</param>
    /// <param name="htmlAttributes">其他属性内容</param>
    /// <returns></returns>
    public static string Span(this HtmlHelper helper, string id, string text, string css, object htmlAttributes)
    {
        //创意某一个Tag的TagBuilder
        var builder = new TagBuilder("span");

        //创建Id,注意要先设置IdAttributeDotReplacement属性后再执行GenerateId方法.
        builder.IdAttributeDotReplacement = "-";
        builder.GenerateId(id);


        //添加属性            
        builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));

        //添加样式
        builder.AddCssClass(css);
        //或者用下面这句的形式也可以: builder.MergeAttribute("class", css);

        //添加内容,以下两种方式均可
        //builder.InnerHtml = text;
        builder.SetInnerText(text);

        //输出控件
        return builder.ToString(TagRenderMode.Normal);

    }

}
public class MvcDiv : IDisposable
{
    private readonly ViewContext _viewContext;
    private bool _disposed;

    public MvcDiv(ViewContext viewContext)
    {
        if (viewContext == null)
        {
            throw new ArgumentNullException("viewContext");
        }

        _viewContext = viewContext;

        // push the new FormContext
        _viewContext.FormContext = new FormContext();
    }
    public void Dispose()
    {
        _disposed = true;
        DivExtensions.EndDiv(_viewContext);
    }
}
/// <summary>
/// div组件内容
/// </summary>
public static class DivExtensions
{

    public static void EndDiv(this HtmlHelper htmlHelper)
    {
        EndDiv(htmlHelper.ViewContext);
    }

    internal static void EndDiv(ViewContext viewContext)
    {
        viewContext.Writer.Write("</div>");
        viewContext.OutputClientValidation();
        viewContext.FormContext = null;
    }

    public static MvcDiv BeginDiv(this HtmlHelper helper, string id, string classvalue)
    {
        TagBuilder tagBuilder = new TagBuilder("div");
        tagBuilder.Attributes["id"] = id;
        if (!string.IsNullOrEmpty(classvalue))
            tagBuilder.AddCssClass(classvalue);
        helper.ViewContext.Writer.Write(tagBuilder.ToString(TagRenderMode.StartTag));
        return new MvcDiv(helper.ViewContext);
    }
}

/// <summary>
/// html内容编辑器
/// </summary>
public static class HtmlditorExtensions
{
    // These values are similar to the defaults used by WebForms
    // when using <asp:TextBox TextMode="MultiLine"> without specifying
    // the Rows and Columns attributes.
    private const int HtmlditorRows = 4;
    private const int HtmlditorColumns = 20;

    private static Dictionary<string, object> implicitRowsAndColumns = new Dictionary<string, object>
        {
            { "rows", HtmlditorRows.ToString(CultureInfo.InvariantCulture) },
            { "cols", HtmlditorColumns.ToString(CultureInfo.InvariantCulture) },
        };

    private static Dictionary<string, object> GetRowsAndColumnsDictionary(int rows, int columns)
    {
        if (rows < 0)
        {
            throw new ArgumentOutOfRangeException("rows", "rows can not set value " + rows.ToString());
        }
        if (columns < 0)
        {
            throw new ArgumentOutOfRangeException("columns", "columns can not set value " + rows.ToString());
        }

        Dictionary<string, object> result = new Dictionary<string, object>();
        if (rows > 0)
        {
            result.Add("rows", rows.ToString(CultureInfo.InvariantCulture));
        }
        if (columns > 0)
        {
            result.Add("cols", columns.ToString(CultureInfo.InvariantCulture));
        }

        return result;
    }

    public static MvcHtmlString Htmlditor(this HtmlHelper htmlHelper, string name)
    {
        return Htmlditor(htmlHelper, name, null /* value */, null /* htmlAttributes */);
    }

    public static MvcHtmlString Htmlditor(this HtmlHelper htmlHelper, string name, object htmlAttributes)
    {
        return Htmlditor(htmlHelper, name, null /* value */, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString Htmlditor(this HtmlHelper htmlHelper, string name, IDictionary<string, object> htmlAttributes)
    {
        return Htmlditor(htmlHelper, name, null /* value */, htmlAttributes);
    }

    public static MvcHtmlString Htmlditor(this HtmlHelper htmlHelper, string name, string value)
    {
        return Htmlditor(htmlHelper, name, value, null /* htmlAttributes */);
    }

    public static MvcHtmlString Htmlditor(this HtmlHelper htmlHelper, string name, string value, object htmlAttributes)
    {
        return Htmlditor(htmlHelper, name, value, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString Htmlditor(this HtmlHelper htmlHelper, string name, string value, IDictionary<string, object> htmlAttributes)
    {
        ModelMetadata metadata = ModelMetadata.FromStringExpression(name, htmlHelper.ViewContext.ViewData);
        if (value != null)
        {
            metadata.Model = value;
        }

        return HtmlditorHelper(htmlHelper, metadata, name, implicitRowsAndColumns, htmlAttributes);
    }

    public static MvcHtmlString Htmlditor(this HtmlHelper htmlHelper, string name, string value, int rows, int columns, object htmlAttributes)
    {
        return Htmlditor(htmlHelper, name, value, rows, columns, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString Htmlditor(this HtmlHelper htmlHelper, string name, string value, int rows, int columns, IDictionary<string, object> htmlAttributes)
    {
        ModelMetadata metadata = ModelMetadata.FromStringExpression(name, htmlHelper.ViewContext.ViewData);
        if (value != null)
        {
            metadata.Model = value;
        }

        return HtmlditorHelper(htmlHelper, metadata, name, GetRowsAndColumnsDictionary(rows, columns), htmlAttributes);
    }

    [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
    public static MvcHtmlString HtmlditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
    {
        return HtmlditorFor(htmlHelper, expression, (IDictionary<string, object>)null);
    }

    [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
    public static MvcHtmlString HtmlditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
    {
        return HtmlditorFor(htmlHelper, expression, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
    public static MvcHtmlString HtmlditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes)
    {
        if (expression == null)
        {
            throw new ArgumentNullException("expression");
        }

        return HtmlditorHelper(htmlHelper,
                              ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData),
                              ExpressionHelper.GetExpressionText(expression),
                              implicitRowsAndColumns,
                              htmlAttributes);
    }

    [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
    public static MvcHtmlString HtmlditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, int rows, int columns, object htmlAttributes)
    {
        return HtmlditorFor(htmlHelper, expression, rows, columns, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TModel"></typeparam>
    /// <typeparam name="TProperty"></typeparam>
    /// <param name="htmlHelper"></param>
    /// <param name="expression"></param>
    /// <param name="rows"></param>
    /// <param name="columns"></param>
    /// <param name="htmlAttributes"></param>
    /// <returns></returns>
    [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
    public static MvcHtmlString HtmlditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, int rows, int columns, IDictionary<string, object> htmlAttributes)
    {
        if (expression == null)
        {
            throw new ArgumentNullException("expression");
        }

        return HtmlditorHelper(htmlHelper,
                              ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData),
                              ExpressionHelper.GetExpressionText(expression),
                              GetRowsAndColumnsDictionary(rows, columns),
                              htmlAttributes);
    }
    
    public static void kindeditorJsImport(TextWriter A)
    {
        A.Write("<script charset='utf-8' src='/kindeditor/kindeditor-all-min.js'></script><script charset='utf-8' src='/kindeditor/kindeditor-zh-CN.js'></script>");
    }
    public static HelperResult kindeditorJsTemo(object A)
    {
        Action<TextWriter> action = kindeditorJsImport;
        return new HelperResult(action);
    }
    [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Justification = "If this fails, it is because the string-based version had an empty 'name' parameter")]
    public static MvcHtmlString HtmlditorHelper(this HtmlHelper htmlHelper, ModelMetadata modelMetadata, string name, IDictionary<string, object> rowsAndColumns, IDictionary<string, object> htmlAttributes, string innerHtmlPrefix = null)
    {
        string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
        if (String.IsNullOrEmpty(fullName))
        {
            throw new ArgumentException("fullName", "name");
        }
        
        Func<object, HelperResult> func = kindeditorJsTemo;
        htmlHelper.Import("header", "kindeditor_JS1", func);

        TagBuilder tagBuilder = new TagBuilder("textarea");
        tagBuilder.GenerateId(fullName);
        tagBuilder.MergeAttributes(htmlAttributes, true);
        tagBuilder.MergeAttributes(rowsAndColumns, rowsAndColumns != implicitRowsAndColumns); // Only force explicit rows/cols
        tagBuilder.MergeAttribute("name", fullName, true);

        // If there are any errors for a named field, we add the CSS attribute.
        ModelState modelState;
        if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out modelState) && modelState.Errors.Count > 0)
        {
            tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
        }

        tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name, modelMetadata));

        string value;
        if (modelState != null && modelState.Value != null)
        {
            value = modelState.Value.AttemptedValue;
        }
        else if (modelMetadata.Model != null)
        {
            value = modelMetadata.Model.ToString();
        }
        else
        {
            value = String.Empty;
        }

        // The first newline is always trimmed when a Htmlditor is rendered, so we add an extra one
        // in case the value being rendered is something like "\r\nHello".
        tagBuilder.InnerHtml = (innerHtmlPrefix ?? Environment.NewLine) + HttpUtility.HtmlEncode(value);

        return new MvcHtmlString("<script type='text/javascript'>var " + fullName + ";KindEditor.ready(function(K){" + fullName + "=CreateEditor(K, '" + fullName + "');});</script>" + tagBuilder.ToString(TagRenderMode.Normal));
    }
}
public class vonHelpWriter
{
    public TextWriter kindeditorJsImport()
    {
        return new StringWriter();
    }
}
//}